﻿namespace JxcLite.Services;

[WebApi, Service]
class BillService(Context context) : ServiceBase(context), IBillService
{
    public Task<PagingResult<BillInfo>> QueryBillsAsync(PagingCriteria criteria)
    {
        return Database.Query<JxBillHead>(criteria).ToPageAsync<BillInfo>();
    }

    public async Task<BillInfo> GetBillAsync(string id)
    {
        BillInfo info = null;
        await Database.QueryActionAsync(async db =>
        {
            info = await db.Query<JxBillHead>().Where(d => d.Id == id).FirstAsync<BillInfo>();
            if (info == null)
            {
                var maxNo = await db.GetMaxBillNoAsync(id);
                info = new BillInfo
                {
                    Type = id,
                    BillNo = maxNo,
                    Status = BizStatus.Save,
                    BillDate = DateTime.Now
                };
            }
            info.Lists = await db.Query<JxBillList>().Where(d => d.HeadId == id).ToListAsync<BillListInfo>();
        });
        return info;
    }

    public async Task<Result> DeleteBillsAsync(List<BillInfo> infos)
    {
        if (infos == null || infos.Count == 0)
            return Result.Error(Language.SelectOneAtLeast);

        if (infos.Exists(d => d.Status != BizStatus.Save))
            return Result.Error(AppCoreLanguage.TipOperateSaveRecord);

        var database = Database;
        var oldFiles = new List<string>();
        var result = await database.TransactionAsync(Language.Delete, async db =>
        {
            foreach (var item in infos)
            {
                await db.DeleteFilesAsync(item.Id, oldFiles);
                await db.DeleteFlowAsync(item.Id);
                await db.DeleteAsync<JxBillList>(d => d.HeadId == item.Id);
                await db.DeleteAsync<JxBillHead>(item.Id);
            }
        });
        if (result.IsValid)
            AttachFile.DeleteFiles(oldFiles);
        return result;
    }

    public async Task<Result> UnVerifyBillsAsync(List<BillInfo> infos)
    {
        if (infos == null || infos.Count == 0)
            return Result.Error(Language.SelectOneAtLeast);

        return await Database.TransactionAsync("反审", async db =>
        {
            foreach (var item in infos)
            {
                var model = await db.QueryByIdAsync<JxBillHead>(item.Id);
                if (model != null)
                {
                    model.Status = BizStatus.Save;
                    await db.SaveAsync(model);
                    await db.AddFlowLogAsync(model.Id, "取消审核", "反审", "取消单证审核");
                }
            }
        });
    }

    public async Task<Result> SaveBillAsync(UploadInfo<BillInfo> info)
    {
        var database = Database;
        var model = await database.QueryByIdAsync<JxBillHead>(info.Model.Id);
        model ??= new JxBillHead();
        model.FillModel(info.Model);

        if (model.Status != BizStatus.Save)
            return Result.Error(AppCoreLanguage.TipOperateSaveRecord);

        var vr = model.Validate(Context);
        if (!vr.IsValid)
            return vr;

        var fileFiles = info.Files?.GetAttachFiles(nameof(BillInfo.Files), "BillFiles");
        return await database.TransactionAsync(Language.Save, async db =>
        {
            if (model.IsNew)
            {
                model.BillNo = await db.GetMaxBillNoAsync(model.Type);
                await db.CreateFlowAsync(BillFlow.GetBizInfo(model));
            }
            if (info.Model.IsVerify)
            {
                model.Status = BizStatus.Verified;
                await db.AddFlowLogAsync(model.Id, "单证审核", "审核", "单证已审核");
            }
            await db.AddFilesAsync(fileFiles, model.Id, key => model.Files = key);
            await db.SaveAsync(model);
            //更新表体数据
            await db.DeleteAsync<JxBillList>(d => d.HeadId == model.Id);
            if (info.Model.Lists != null && info.Model.Lists.Count > 0)
            {
                var index = 1;
                foreach (var item in info.Model.Lists)
                {
                    var list = new JxBillList();
                    list.FillModel(item);
                    list.HeadId = model.Id;
                    list.SeqNo = index++;
                    await db.SaveAsync(list);
                }
            }
            info.Model.Id = model.Id;
        }, info.Model);
    }
}